/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package am.aua.renju.databaseaccess;

import am.aua.renju.entity.Player;
import java.util.List;
import javax.persistence.*;

/**
 *
 * @author ara
 */
public class UserOperations implements IUserOperations {

    static UserOperations instance;
    private EntityManagerFactory emf;

    public static IUserOperations getInstance() {
        if (instance == null) {
            instance = new UserOperations();
        }
        return instance;
    }

    private UserOperations() {
        emf = Persistence.createEntityManagerFactory("RenjuDPU");
    }

    @Override
    public void createUser(Player user) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction et = em.getTransaction();
        et.begin();
        em.persist(user);
        et.commit();
        em.close();
    }

    /**
     * Not implemented yet
     */
    @Override
    public void deleteUser(String email) {
        EntityManager em = emf.createEntityManager();
        em.remove(this.getUser(email));
        em.close();
    }

    @Override
    public Player getUser(String email) {
        EntityManager em = emf.createEntityManager();
        TypedQuery<Player> query = em.createQuery("SELECT u FROM Player u WHERE u.email=:email", Player.class).
                setParameter("email", email);
        try {
            Player a = query.getSingleResult();
            return a;
        } catch (NoResultException ex) {
            return null;
        } finally {
            em.close();
        }
    }

    @Override
    public Player getUserByNickname(String nickname) {
        EntityManager em = emf.createEntityManager();
        TypedQuery<Player> query = em.createQuery("SELECT u FROM Player u WHERE u.nickname=:nickname", Player.class).
                setParameter("nickname", nickname);
        Player result;
        try {
            result = query.getSingleResult();
        } catch (NoResultException ex) {
            return null;
        } finally {
            em.close();
        }
        return result;
    }

    @Override
    public void updateNickname(String email, String newNickname) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createQuery("UPDATE Player u SET u.nickname=:newNickname WHERE u.email=:email").
                setParameter("newNickname", newNickname).setParameter("email", email);
        EntityTransaction et = em.getTransaction();
        et.begin();
        query.executeUpdate();
        et.commit();
        em.close();
    }

    @Override
    public void updatePassword(String email, String newPassword) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createQuery("UPDATE Player u SET u.password=:newPassword WHERE u.email=:email").
                setParameter("newPassword", newPassword).setParameter("email", email);
        EntityTransaction et = em.getTransaction();
        et.begin();
        query.executeUpdate();
        et.commit();
        em.close();
    }

    @Override
    public void close() {
        if (emf.isOpen()) {
            emf.close();
        }
        Operations.instance = null;
    }

    @Override
    public void updateUserRating(String email, int newRating) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createQuery("UPDATE Player u SET u.rating=:newRating WHERE u.email=:email").
                setParameter("newRating", newRating).setParameter("email", email);
        EntityTransaction et = em.getTransaction();
        et.begin();
        query.executeUpdate();
        et.commit();
        em.close();
    }

    @Override
    public List<Player> getTop10Players() {
        EntityManager em = emf.createEntityManager();
        TypedQuery<Player> query = em.createQuery("SELECT u FROM Player u ORDER BY u.rating DESC", Player.class).
                setFirstResult(0).setMaxResults(10);
        List<Player> result;
        try {
            result = query.getResultList();
        } catch (NoResultException ex) {
            return null;
        } finally {
            em.close();
        }
        return result;
    }
}
